#include "phs_net.h"

static phs_udp udp;

void phs_initUdp(int adr){
        udp.verihl = 0x45;
        udp.zero = 0x00;
        udp.flags = 0;
        udp.id = 0;
        udp.ttlprot = htons(0x0311);
        udp.dip = htonl(0xffffffff);
        udp.sip = adr;
        //upd setup
        udp.sport = htons(50000);
        udp.dport = htons(50000);
        udp.crc = 0xffff;
}

void phs_initSourceIP(int adr) {
        phs_initUdp(adr);
        printk(KERN_INFO "PHS_Net: adresa zariadenia inicializovana: %x\n", adr);
}

unsigned char* connectdata(unsigned char *buf, int len){ //connect data
        char *buf2;
	int i;
        printk(KERN_INFO" PHS_Net: connectdata: function called\n");
        udp.len = htons(len + 8);
        udp.tl = htons(len + 28);
        udp.ipcrc = 0x0000;

        //odkomentovane mnou
        memset(&udp.data, 0, 1000);
        memcpy(&udp.data, buf, len);

        buf2 = (char *) &(udp);
        printk(KERN_INFO"PHS_Net: connectdata: data connected\n");

        udp.ipcrc = ip_fast_csum(buf2, 5);

        printk(KERN_INFO"PHS_Net: connectdata: crc is %x\n", udp.ipcrc);
	for (i=0; i<(len); i++){
//                printk(KERN_INFO" %x", *pom2);
        }
	printk(KERN_INFO "--end\n");
        return buf2;
}

/**
 *  nastavi DA,SA,TYPE v L2 ramci
**/
int phsInitMacAddr(struct sk_buff* skb, const unsigned char* sa, const unsigned char* da){
        int rc = -EINVAL;
        switch (skb->dev->type) {
                case ARPHRD_IEEE802_TR:
                case ARPHRD_ETHER:
                case ARPHRD_LOOPBACK:
                        rc = dev_hard_header(skb, skb->dev, ETH_P_IP, da, sa, skb->len);
                        if (rc > 0) rc = 0;
                        break;
                default:
                        printk(KERN_INFO "phs: device type not supported: %d\n",skb->dev->type);
        }
        return rc;
}

void pf_send_pdu(const unsigned char *data, int length)
{
        struct net_device *dev; // potrebujem ten device
        struct sk_buff *skb;
        uint err;
        unsigned char aaa[6];
        aaa[0] =  0xFF;
        aaa[1] =  0xFF;
        aaa[2] =  0xFF;
        aaa[3] =  0xFF;
        aaa[4] =  0xFF;
        aaa[5] =  0xFF;

        // zistim identifikator sietoveho devicu, nutne drzat rtnl_lock
        rtnl_lock();
        dev = dev_get_by_name(&init_net, PF_DEV);
        rtnl_unlock();

        if (dev == NULL) {
                printk(KERN_ERR "PHS_Net: dev NULL\n");
                return;
        }
        printk(KERN_INFO "PHS_Net: dev found [%s]\n", dev->name);
        skb = dev_alloc_skb(length+1);
        if (!skb) {
		printk(KERN_ERR "PHS_Net: nedostali sme skb!");
                return;
	}

        skb->dev = dev;
	skb->pkt_type = PACKET_OUTGOING;
        skb->protocol = htons(ETH_P_IP);

        memcpy(__skb_put(skb, length), data, length);

        phsInitMacAddr(skb, dev->dev_addr, aaa); // co robi br->group_addr ???

        // PT_INET -> protocol family
        err = NF_HOOK(PF_INET, NF_INET_POST_ROUTING, skb, NULL, dev, dev_queue_xmit);
        printk(KERN_INFO "PHS_Net: pf_send_pdu: result: %d\n", err);
        //kfree(skb);
}

int phs_sendHello(char *buf, int len){
        char *buf2;

        buf2 = connectdata(buf, len);
	if (!buf2) {
		printk(KERN_INFO "PHS_Net: ConnectData function return -1 FAIL!");
		return -1;
	}
        printk(KERN_INFO "PHS_Net: phs_sendHello: data connected \n");
        len+=28;//20 IP hlavicka + 8 UDP
	printk(KERN_INFO "PHS_Net: len = %d\n", len);
        pf_send_pdu(buf2, len);
	//vfree((phs_udp *) buf2);
        return 0;
}
